home *** CD-ROM | disk | FTP | other *** search
- /* */
- /* UUARC V1.3 04/10/93 */
- /* J.G.Brandon */
- /* */
- /* */
- /* Archiving system based on the 'UU' encoding/decoding */
- /* algorythms. */
- /* */
- /* Written in 'C' for the public domain using NorthC V1.3 */
- /* on a Commodore Amiga. Ought to compile/run under most */
- /* compilers/environments. */
- /* */
- /* No system specific commands/libraries/includes/headers */
- /* used to make 'C' source portable. The only system */
- /* specific part of the program is the pre-processor */
- /* defined function to identify 'directory separator' */
- /* characters, used to separate file-names from their */
- /* paths. */
- /* */
-
-
-
- /* If required, comment the next line to stop checksums being added */
- /* (This only effects encoding output, decoding will still check */
- /* checksums if checksums are present) */
- #define ADDCHECK
-
-
-
- /* Title/version definitions */
-
- #define TITLE "UUArc"
- #define AUTHOR "Miss J.G.Brandon"
- #define VERSION 1
- #define REVISION 3
- #define TITLESTR "\n%s Version %d.%d by %s %s.\n\n"
- #define TITLESTRPAR TITLE, VERSION, REVISION, AUTHOR, __DATE__
-
-
-
- /* Required standard libraries */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <stdlib.h>
- #include <signal.h>
-
- /* When are standard includes not standard includes? */
- /* When they miss out definitions that should be there. */
- /* I'll name no names; but it's a very popular compiler... */
- /* (VERY naughty, as it sets the _STDC_ flag to indicate */
- /* that it is completely ANSI standard conforming; */
- /* and these are just the ones missed out that this */
- /* program needs, there are many more.) */
-
- #ifndef EXIT_SUCCESS
- #define EXIT_SUCCESS 0
- #endif
-
- #ifndef EXIT_FAILURE
- #define EXIT_FAILURE 20
- #endif
-
- #ifndef L_tmpnam
- #define L_tmpnam 0x0FF
- #endif
-
-
- /* Define conditional close function; attempts to close a file indicated */
- /* by the supplied file pointer if the pointer is not null */
-
- #define COND_CLOSE(fptr) if (fptr != NULL) fclose(fptr)
-
-
- /* Define 'directory-separator' identifier - system specific unfortunately */
-
- #define DIR_CHAR(c) ((c == ':') || (c == '/'))
-
-
- /* Define uuencoding/decoding/checking functions */
-
- #define VALIDATE(c) ((c < 0x020) || (c > 0x060))
- #define DECODE(c) ((c - 0x020) & 0x03F)
- #define ENCODE(c) (c ? ((c & 0x03F) + 0x020) : 0x060)
-
-
- /* Definitions required by program */
-
- #define LISTCOM 'l'
- #define TESTCOM 't'
- #define EXTRACTCOM 'x'
- #define DELETECOM 'd'
- #define ADDCOM 'a'
- #define MOVEOPT 'm'
- #define PATHOPT 'p'
-
- #define BUFSIZE 0x0FF
-
- #define ENCODESIZE 45
- #define DEFAULTMODE 0744
-
- #define NOFILE 0
- #define FOUNDFILE 1
-
- #define DATALINE 0
- #define BEGINLINE 1
- #define ENDLINE 2
- #define SIZELINE 3
- #define BADLINE 4
-
- #define STRIPPATH 0
- #define LEAVEPATH 1
-
- #define LEAVEFILE 0
- #define MOVEFILE 1
-
- #define SHOWUSAGE 0
- #define NOUSAGE 1
-
- #define DUNNO 0
- #define YES 1
- #define NO 2
-
- #define CHECKSIZE 64
-
-
-
- /* If this is ANSI 'C', do function prototyping */
-
- #ifdef _STDC_
- char *prname(char *, int);
- int anycasecmp(char *, char *)
- int filecmp(char *, char *[], int)
- void pr_head(char *)
- void pr_tail(void)
- void operout(char *, int)
- void succout(char *, int)
- void errsout(long)
- void usage(FILE *)
- void cleanexit(int)
- void errorexit(char *, int)
- void abnormalexit(int)
- int listarc(void)
- int deletearc(char *, char *[], int)
- int extractarc(char, char *[], int)
- int fileread(char *)
- int addarc(char *[], int)
- #endif
-
-
-
- /* Globally accessable archive, file and temporary file details */
-
- FILE *arc_fptr = NULL, *file_fptr = NULL, *temp_fptr = NULL;
- char temp_name[L_tmpnam] = "";
-
- /* Globally accessable number of errors counter */
-
- long numerrors = 0;
-
- /* Globally accessable path strip flag */
-
- int pathflag = STRIPPATH;
-
- /* Globally accessable move files flag */
-
- int moveflag = LEAVEFILE;
-
-
-
- /* Strip path name from a filename if required */
-
- char *prname(filename, flag)
- char *filename;
- int flag;
- {
- char *stripname;
-
- /* If full path has been requested, leave it in */
- if (flag == LEAVEPATH)
- return filename;
-
- /* Hunt from left to right for a path-indicator character */
- for(stripname = filename+strlen(filename);
- ((stripname > filename) && (!DIR_CHAR(*stripname)));
- stripname--)
- ;
-
- /* If path-indicator character found, increment pointer to */
- /* point to start of file name */
- if DIR_CHAR(*stripname)
- stripname++;
-
- /* Return pointer to filename without path extension */
- return stripname;
- }
-
-
-
- /* String comparison, ignoring case - result same as strcmp */
-
- int anycasecmp(string1, string2)
- char *string1, *string2;
- {
- int i;
- for (i = 0; toupper(string1[i]) == toupper(string2[i]); i++)
- if (string1[i] == '\0')
- return 0;
- return toupper(string1[i]) - toupper(string2[i]);
- }
-
-
-
- /* Check filename against list of given filenames */
-
- int filecmp(filename, argv, argc)
- char *filename;
- char *argv[];
- int argc;
- {
- int targc;
- int filematch = NOFILE;
- if (argc == 3)
- filematch = FOUNDFILE;
- else
- for (targc = 3; targc < argc; targc++)
- if (anycasecmp(prname(filename, pathflag),
- prname(argv[targc], pathflag)) == 0)
- filematch = FOUNDFILE;
- return filematch;
- }
-
-
-
- /* Print archive header information */
-
- void pr_head(archive)
- char *archive;
- {
- printf(" archive '%s':\n", archive);
- printf("---------------------------------------------\n");
- }
-
-
-
- /* Print archive tail information */
-
- void pr_tail()
- {
- printf("---------------------------------------------\n");
- }
-
-
-
- /* Outputs details of an operation, taking plurals into account */
-
- void operout(operstr,numfiles)
- char *operstr;
- int numfiles;
- {
- if (numfiles == 0)
- printf("No ");
- else
- printf("%d ",numfiles);
-
- if (numfiles != 1)
- printf("files ");
- else
- printf("file ");
-
- printf("%s.\n",operstr);
- }
-
-
-
- /* Outputs details of success of an operation */
-
- void succout(operstr, numerrs)
- char *operstr;
- int numerrs;
- {
- if (numerrs == 0)
- printf("%s successful.\n\n",operstr);
- else
- fprintf(stderr,"%s not entirely successful.\n\n",operstr);
- }
-
-
-
- /* Outputs details of errors, taking plurals into account */
-
- void errsout(numerrs)
- long numerrs;
- {
- if (numerrs != 0) {
- fprintf(stderr, "%d error", numerrs);
- if (numerrs != 1)
- fprintf(stderr, "s.\n");
- else
- fprintf(stderr, ".\n");
- }
- }
-
-
-
- /* Sends details of command usage to output stream 'ostrm' */
-
- void usage(ostrm)
- FILE *ostrm;
- {
- fprintf(ostrm,
- "\nUSAGE:\t%s -<command>[%c][%c] <archive> [<filename> ... ]\n",
- TITLE, PATHOPT, MOVEOPT);
-
- fprintf(ostrm, "\nWhere <command> is one of-\n");
- fprintf(ostrm, "\t%c = List contents of <archive>.\n", LISTCOM);
- fprintf(ostrm, "\t%c = Test contents of <archive>.\n", TESTCOM);
- fprintf(ostrm, "\t%c = Add <filename(s)> to <archive>.\n", ADDCOM);
- fprintf(ostrm, "\t%c = Extract <filenames> from <archive>.\n", EXTRACTCOM);
- fprintf(ostrm, "\t (All files if no <filenames> given.)\n");
- fprintf(ostrm, "\t%c = Delete <filenames> from <archive>.\n", DELETECOM);
- fprintf(ostrm, "\t (All files if no <filenames> given.)\n");
-
- fprintf(ostrm,
- "\nIf included after the archiver command, the '%c' option\n",
- PATHOPT);
- fprintf(ostrm,
- "specifies full path names to be considered; otherwise path\n");
- fprintf(ostrm,
- "names will be ignored.\n");
-
- fprintf(ostrm,
- "\nIf included after an add/extract archiver command, the '%c'\n",
- MOVEOPT);
- fprintf(ostrm,
- "option specifies files to be moved from source, i.e. source\n");
- fprintf(ostrm,
- "files will be deleted; otherwise they are left as is.\n");
-
- fprintf(ostrm,
- "\nIf applicable, <archive> must include the '.uue' extension.\n\n");
- }
-
-
-
- /* A 'clean' exit routine; closes any open files, deletes the temporary */
- /* file if used, and exits with return code 'retcode' */
-
- void cleanexit(retcode)
- int retcode;
- {
- COND_CLOSE(arc_fptr);
- COND_CLOSE(file_fptr);
- COND_CLOSE(temp_fptr);
- if (strcmp(temp_name,"") != 0)
- remove(temp_name);
-
- exit(retcode);
- }
-
-
-
- /* Exit routine for errors; displays error 'errorstr' and command usage */
- /* to the standard error output stream, then 'cleanexit's with a failure */
- /* return code */
-
- void errorexit(errorstr, usageflag)
- char *errorstr;
- int usageflag;
- {
- fprintf(stderr, "\n\aERROR: %s.\n\n", errorstr);
-
- if (usageflag == SHOWUSAGE)
- usage(stderr);
-
- cleanexit(EXIT_FAILURE);
- }
-
-
-
- /* Deal with abnormal program termination */
-
- void abnormalexit(sig)
- int sig;
- {
- fprintf(stderr, "\n\aERROR: Program aborted.\n\n");
- cleanexit(EXIT_FAILURE);
- }
-
-
-
- /* List files in the opened archive */
-
- int listarc()
- {
- char buffer[BUFSIZE], filestr[BUFSIZE];
- int filemode, numfiles = 0;
-
- /* Go through archive until error/end-of-file, listing any files found */
-
- while(fgets(buffer, BUFSIZE, arc_fptr) != NULL) {
- if (sscanf(buffer, "begin %o %s", &filemode, filestr) == 2) {
- numfiles++;
- printf("Found - %s\n", filestr);
- }
- }
-
- return numfiles;
- }
-
-
-
- /* Delete files from an archive */
-
- int deletearc(arcname, argv, argc)
- char *arcname;
- char *argv[];
- int argc;
- {
- char buffer[BUFSIZE], filestr[BUFSIZE], arcfile[BUFSIZE];
- int filemode, numdel = 0, fileflag = NOFILE;
- int deleteflag = NOFILE, lastdelete = NOFILE;
- int linetype, lastline = DATALINE;
- long expectedsize;
-
-
- /* Open archive for input, and a temporary file for output/input */
-
- if (arc_fptr == NULL)
- if ((arc_fptr = fopen(arcname, "r")) == NULL)
- errorexit("Can't open archive for input", SHOWUSAGE);
-
- if ((temp_fptr = fopen((tmpnam(temp_name)), "w+")) == NULL)
- errorexit("Can't open temporary file", NOUSAGE);
-
-
- /* Deal with each line in archive until end-of-file/error */
-
- while(fgets(buffer, BUFSIZE, arc_fptr) != NULL) {
-
-
- /* Signal a data line by default */
- linetype = DATALINE;
-
-
- /* Deal with a begin statement */
-
- if (sscanf(buffer, "begin %o %s", &filemode, filestr) == 2) {
-
- /* Indicate command line */
- linetype = BEGINLINE;
-
- /* If already dealing with a file, error - missing end */
- if (fileflag == FOUNDFILE) {
- fprintf(stderr, "Missing 'end' - %s\n", arcfile);
- numerrors++;
- printf("Deleted - %s\n", arcfile);
- numdel++;
- }
-
- /* Remember file name, signal that a file's been found */
- strcpy(arcfile, filestr);
- fileflag = FOUNDFILE;
-
- /* Store previous delete status */
- lastdelete = deleteflag;
-
- /* Signal whether or not file is to be deleted */
- deleteflag = filecmp(arcfile, argv, argc);
-
- }
-
-
- /* Deal with a size statement */
-
- if (sscanf(buffer, "size %d", &expectedsize) == 1) {
-
- /* Indicate command line */
- linetype = SIZELINE;
-
- /* A size statement is only expected after an end statement */
- if (lastline != ENDLINE) {
- fprintf(stderr, "Misplaced 'size' - %s\n", arcfile);
- numerrors++;
- }
- }
-
-
- /* Copy lines not to be deleted from archive to temporary file */
-
- if (!((deleteflag == FOUNDFILE) ||
- ((lastline == ENDLINE) &&
- (linetype == SIZELINE) &&
- (lastdelete == FOUNDFILE))))
- if (fputs(buffer, temp_fptr) == EOF)
- errorexit("File error writing to temporary file", NOUSAGE);
-
-
- /* Deal with an end statement */
-
- if (strncmp(buffer, "end", 3) == 0) {
-
- /* Indicate command line */
- linetype = ENDLINE;
-
- /* An end statement; so make sure we had a start statement */
- if (fileflag == FOUNDFILE) {
- /* Signal that file has been processed, and increment */
- /* number of files deleted counter if necessary */
- if (deleteflag == FOUNDFILE) {
- printf("Deleted - %s\n", arcfile);
- numdel++;
- }
- else
- printf("Skipped - %s\n", arcfile);
- }
- else {
- /* If no relevant start statement, error - missing begin */
- fprintf(stderr, "Missing 'begin' - ?\n");
- numerrors++;
- }
-
- /* Store previous delete status */
- lastdelete = deleteflag;
-
- /* Clear deletion and processing a file */
- deleteflag = NOFILE;
- fileflag = NOFILE;
-
- }
-
- lastline = linetype;
-
- }
-
- /* If we hit end of archive file whilst still expecting data, error */
- if (fileflag != NOFILE) {
- fprintf(stderr, "Missing (final) 'end' - %s\n", arcfile);
- numerrors++;
- printf("Deleted - %s\n", arcfile);
- numdel++;
- }
-
-
- /* Go back to start of temporary file */
- rewind(temp_fptr);
-
- /* Close archive file, and re-open it (cleared) for output */
- COND_CLOSE(arc_fptr);
- if ((arc_fptr = fopen(arcname, "w")) == NULL)
- errorexit("Can't open archive for output", SHOWUSAGE);
-
- /* Copy contents of temporary file to archive file */
- while(fgets(buffer, BUFSIZE, temp_fptr) != NULL)
- if (fputs(buffer, arc_fptr) == EOF)
- errorexit("File error writing to archive file", NOUSAGE);
-
-
- /* Return number of files deleted */
- return numdel;
- }
-
-
-
- /* Extract/Test files in the opened archive */
-
- int extractarc(extcom, argv, argc)
- char extcom;
- char *argv[];
- int argc;
- {
- char buffer[BUFSIZE], filestr[BUFSIZE], arcfile[BUFSIZE], outstr[BUFSIZE];
- int ic1, ic2, ic3, ic4;
- int filemode, numfiles = 0, fileflag = NOFILE;
- unsigned int checksum;
- int checkflag;
- int linetype, lastline = DATALINE, numdata, datapos, linelen;
- long filesize = 0, expectsize;
-
-
- /* Go through archive until error/end-of-file */
-
- while(fgets(buffer, BUFSIZE, arc_fptr) != NULL) {
-
-
- /* As a default, assume line to be a line of UUencoded data */
-
- linetype = DATALINE;
-
-
- /* Deal with a begin statement */
-
- if (sscanf(buffer, "begin %o %s", &filemode, filestr) == 2) {
-
- /* Flag line as being a command line */
- linetype = BEGINLINE;
-
- /* If already dealing with a file, error - missing end */
- if (fileflag == FOUNDFILE) {
- fprintf(stderr, "Missing 'end' - %s\n", arcfile);
- numerrors++;
- COND_CLOSE(file_fptr);
- file_fptr = NULL;
- /* If just testing archive, indicate that file has been */
- /* processed and increment number of files counter */
- if (extcom == TESTCOM) {
- printf("%21d - %s\n", filesize, arcfile);
- numfiles++;
- }
- else {
- /* If extracting, indicate that file has been */
- /* processed and increment number of files counter */
- /* if necessary */
- if (file_fptr != NULL) {
- printf("%21d - %s\n", filesize, arcfile);
- numfiles++;
- }
- else
- printf("Skipped - %s\n", arcfile);
- }
- }
-
- /* Remember file name, signal that a file's been found, */
- /* set file size counter to 0, and reset checksum status */
- strcpy(arcfile, filestr);
- fileflag = FOUNDFILE;
- filesize = 0;
- checkflag = DUNNO;
-
- /* If not just testing the archive, open file for output */
- if ((extcom != TESTCOM) &&
- (filecmp(arcfile, argv, argc) == FOUNDFILE))
- if ((file_fptr = fopen(prname(arcfile,
- pathflag), "w")) == NULL) {
- fprintf(stderr, "Can't open for output - %s\n",
- prname(arcfile, pathflag));
- numerrors++;
- }
- }
-
-
- /* Deal with an end statement */
-
- if (strncmp(buffer, "end", 3) == 0) {
-
- /* Flag line as being a command line */
- linetype = ENDLINE;
-
- /* An end statement; so make sure we had a start statement */
- if (fileflag == FOUNDFILE) {
- /* If just testing archive, indicate that file has been */
- /* processed and increment number of files counter */
- fileflag = NOFILE;
- if (extcom == TESTCOM) {
- printf("%21d - %s\n", filesize, arcfile);
- numfiles++;
- }
- else {
- /* If extracting, indicate that file has been */
- /* processed and increment number of files counter */
- /* if necessary */
- if (file_fptr != NULL) {
- printf("%21d - %s\n", filesize, arcfile);
- numfiles++;
- }
- else
- printf("Skipped - %s\n", arcfile);
- }
- }
- else {
- /* If no relevant start statement, error - missing begin */
- fprintf(stderr, "Missing 'begin' - ?\n");
- numerrors++;
- }
-
- COND_CLOSE(file_fptr);
- file_fptr = NULL;
-
- }
-
-
- /* Deal with a size statement */
-
- if (sscanf(buffer, "size %d", &expectsize) == 1) {
-
- /* Flag line as being a command line */
- linetype = SIZELINE;
-
- /* A size statement is only expected after an end statement */
- if (lastline != ENDLINE) {
- fprintf(stderr, "Misplaced 'size' - %s\n", arcfile);
- numerrors++;
- }
- else {
- /* Check the size of the file was as expected */
- if ((filesize != expectsize) &&
- ((extcom == TESTCOM) || (file_fptr != NULL))) {
- fprintf(stderr, "File size wrong - %s\n", arcfile);
- numerrors++;
- }
- }
- }
-
-
- /* Deal with a line of data */
-
- if (linetype == DATALINE) {
-
- /* Only want data lines within begin/end statements */
- /* And only want to bother decoding file if required */
- if ((fileflag == FOUNDFILE) &&
- ((extcom == TESTCOM) || (file_fptr != NULL))) {
-
- /* Strip any white-space characters from end of line */
- /* that aren't pure space characters */
- if ((datapos = strlen(buffer)-1) >= 0)
- while (isspace(buffer[datapos]) &&
- (buffer[datapos] != ' ') &&
- (datapos >= 0)) {
- buffer[datapos] = '\0';
- datapos--;
- }
-
- linelen=strlen(buffer);
-
- /* If any data is in the line */
- if (linelen > 0) {
-
- /* Reset line checksum */
- checksum = 0;
-
- /* Error if any characters not within limits */
- for(datapos = 0;
- ((datapos < linelen) && (linetype == DATALINE));
- datapos++)
- if VALIDATE(buffer[datapos]) {
- fprintf(stderr,
- "Corrupt byte in line - %s\n", arcfile);
- numerrors++;
- linetype = BADLINE;
- }
-
-
- /* Attempt to decode line */
- if (linetype == DATALINE) {
-
- /* Fetch total number of bytes to written out */
- numdata = DECODE(*buffer);
- /* Decode relevant number of bytes from archive */
- for(datapos = 1;
- (((datapos+numdata)<linelen) && (numdata>0));
- datapos+=4) {
- ic1 = DECODE(buffer[datapos]);
- ic2 = DECODE(buffer[datapos+1]);
- ic3 = DECODE(buffer[datapos+2]);
- ic4 = DECODE(buffer[datapos+3]);
- outstr[numdata+2] = ic1 << 2 | ic2 >> 4;
- outstr[numdata+1] = ic2 << 4 | ic3 >> 2;
- outstr[numdata] = ic3 << 6 | ic4 ;
- checksum = ( checksum +
- outstr[numdata+2] +
- outstr[numdata+1] +
- outstr[numdata] ) % CHECKSIZE;
- numdata-=3;
- }
-
- /* Error if not enough data in line */
- if ((numdata > 0) || ((checkflag == YES) &&
- ((linelen-datapos) < 1))) {
- fprintf(stderr,
- "Data line too short - %s\n", arcfile);
- numerrors++;
- linetype = BADLINE;
- }
-
- /* If line is okay, and checksums have been */
- /* present, then analyse checksum */
- if ((checkflag == YES) && (linetype == DATALINE)) {
- if (checksum != DECODE(buffer[datapos])) {
- fprintf(stderr,
- "Checksum error - %s\n", arcfile);
- numerrors++;
- linetype = BADLINE;
- }
- }
-
- /* Error if too much data in line - allow extra */
- /* pure space characters though */
- if (((checkflag != NO) && ((linelen-datapos) > 2)) ||
- ((checkflag == NO) && ((linelen-datapos) > 1))) {
- if (checkflag == NO)
- datapos++;
- else
- datapos=datapos + 2;
- while((datapos<linelen)
- && (linetype != BADLINE))
- if (buffer[datapos++] != ' ')
- linetype = BADLINE;
- if (linetype == BADLINE) {
- fprintf(stderr,
- "Data line too long - %s\n", arcfile);
- numerrors++;
- }
- }
-
- /* If the line was okay, and file checksum status */
- /* is still unknown, then establish the status */
- if ((checkflag == DUNNO) && (linetype == DATALINE)) {
- if ((linelen-datapos) == 0)
- checkflag = NO;
- else {
- if (checksum == DECODE(buffer[datapos])) {
- checkflag = YES;
- }
- else {
- fprintf(stderr,
- "Bad checksum/linesize - %s\n",
- arcfile);
- numerrors++;
- linetype = BADLINE;
- }
- }
- }
- }
-
- /* If line is completely error free */
- if (linetype == DATALINE) {
- /* Increment file size counter */
- filesize += (numdata = DECODE(*buffer));
- /* If file has been opened for output, write out */
- /* decoded bytes */
- if (file_fptr != NULL)
- while(numdata > 0) {
- if (fputc(outstr[numdata+2],
- file_fptr) == EOF)
- errorexit("File error writing file",
- NOUSAGE);
- numdata--;
- }
- }
-
- }
-
- else {
- fprintf(stderr, "No data, empty line - %s\n", arcfile);
- numerrors++;
- }
-
- }
-
- }
-
- lastline = linetype;
-
- }
-
- /* If we hit end of archive file whilst still expecting data, error */
- if (fileflag != NOFILE) {
- fprintf(stderr, "Missing (final) 'end' - %s\n", arcfile);
- numerrors++;
- /* If just testing archive, indicate that file has been */
- /* processed and increment number of files counter */
- if (extcom == TESTCOM) {
- printf("%21d - %s\n", filesize, arcfile);
- numfiles++;
- }
- else {
- /* If extracting, indicate that file has been */
- /* processed and increment number of files counter */
- /* if necessary */
- if (file_fptr != NULL) {
- printf("%21d - %s\n", filesize, arcfile);
- numfiles++;
- }
- else
- printf("Skipped - %s\n", arcfile);
- }
- }
-
- /* Return number of files extracted */
- return numfiles;
- }
-
-
-
- /* Read from file, dealing with with any errors */
-
- int fileread(buf)
- char *buf;
- {
- int numread;
-
- /* Read data into buffer */
- numread = fread(buf, sizeof(char), ENCODESIZE, file_fptr);
-
- /* If an error occured, exit cleanly with an error */
- if ferror(file_fptr)
- errorexit("File error reading file", NOUSAGE);
-
- /* Return number of bytes read */
- return numread;
- }
-
-
-
- /* Add files specified to the opened archive */
-
- int addarc(argv, argc)
- char *argv[];
- int argc;
- {
- char buffer[BUFSIZE], outstr[BUFSIZE];
- int ic1, ic2, ic3, oc1, oc2, oc3, oc4;
- int inpos, outpos, targc, numfiles = 0, n;
- long filesize;
- #ifdef ADDCHECK
- unsigned int checksum;
- #endif
-
- /* Repeat for each filename given */
- for (targc = 3; targc < argc; targc++) {
-
- /* Reset filesize counter */
- filesize = 0;
-
- /* Open file for input */
- if ((file_fptr = fopen(argv[targc], "r")) == NULL) {
- fprintf(stderr, "Can't open for input - %s\n", argv[targc]);
- numerrors++;
- }
- else {
-
- /* Write begin statement */
- fprintf(arc_fptr, "\nbegin %o %s\n",
- DEFAULTMODE, prname(argv[targc], pathflag));
-
- /* Read and encode from file whilst data is available */
-
- do {
-
- n = fileread(buffer);
-
- /* Encode number of bytes read into first character */
- /* in line */
- *outstr = ENCODE(n);
-
- #ifdef ADDCHECK
- /* Reset checksum */
- checksum = 0;
- #endif
-
- /* Encode data */
- outpos = 1;
- for(inpos = 0; inpos < n; inpos += 3) {
- ic1 = buffer[inpos];
- ic2 = buffer[inpos+1];
- ic3 = buffer[inpos+2];
- oc1 = ic1 >> 2;
- oc2 = (ic1 << 4) & 0x030 | (ic2 >> 4) & 0x00F;
- oc3 = (ic2 << 2) & 0x03C | (ic3 >> 6) & 0x003;
- oc4 = ic3 & 0x03F;
- outstr[outpos] = ENCODE(oc1);
- outstr[outpos+1] = ENCODE(oc2);
- outstr[outpos+2] = ENCODE(oc3);
- outstr[outpos+3] = ENCODE(oc4);
- outpos += 4;
- #ifdef ADDCHECK
- checksum = ( checksum + ic1 + ic2 + ic3 ) % CHECKSIZE;
- #endif
- }
-
- /* Add termination to output string */
- #ifdef ADDCHECK
- outstr[outpos] = ENCODE(checksum);
- outpos++;
- #endif
- outstr[outpos] = '\n';
- outstr[outpos+1] = '\0';
-
- /* Write data into archive */
- if (fputs(outstr, arc_fptr) == EOF)
- errorexit("File error writing to archive file", NOUSAGE);
-
- filesize += n;
-
- } while (n > 0);
-
- /* Write end statement */
- fprintf(arc_fptr, "end\n");
- fprintf(arc_fptr, "size %d\n", filesize);
-
- /* Indicate that file has been processed */
- printf("%21d - %s\n", filesize, prname(argv[targc], pathflag));
-
- numfiles++;
-
- /* Close file */
- COND_CLOSE(file_fptr);
- file_fptr = NULL;
-
- /* In the case of a move command, delete file */
- if (moveflag == MOVEFILE)
- remove(argv[targc]);
-
- }
-
- }
-
- return numfiles;
- }
-
-
-
- /* Main entry point, taking standard "main" style parameters */
-
- void main(argc, argv)
- int argc;
- char *argv[];
- {
- char command[BUFSIZE];
- int numfiles, numdel, comlen, compos;
-
- /* Trap program interruption, to exit cleanly */
- /* A 'certain' compiler gives warnings -the code */
- /* is correct, the compiler is wrong (sorry, but */
- /* according to the K&R book, and just about every */
- /* other compiler - a signal handler is supposed */
- /* supposed to return void, _NOT_ int) - program */
- /* will still work, presumably to just ignore the */
- /* compiler warnings in this curcumstance is okay */
- #ifdef SIGABRT
- signal(SIGABRT, abnormalexit);
- #endif
- #ifdef SIGINT
- signal(SIGINT, abnormalexit);
- #endif
- #ifdef SIGTERM
- signal(SIGTERM, abnormalexit);
- #endif
-
- /* Display program title */
- printf(TITLESTR, TITLESTRPAR);
-
- /* If no arguments specified, display usage and exit */
- if (argc < 2) {
- usage(stderr);
- cleanexit(EXIT_FAILURE);
- }
-
- /* If only argument is a question-mark, display usage and exit */
- if (strcmp(argv[1], "?") == 0) {
- usage(stdout);
- cleanexit(EXIT_FAILURE);
- }
-
- /* Check existance of an archiver command */
- if (sscanf(argv[1], "-%s", command) != 1)
- errorexit("Archiver command missing/invalid", SHOWUSAGE);
- comlen = strlen(command);
-
- /* Check command is right length */
- if ((comlen < 1) || (comlen > 3))
- errorexit("Archiver command/options missing/invalid", SHOWUSAGE);
-
- /* Deal with flags if given */
- compos = 1;
- while (compos < comlen) {
- switch(tolower(command[compos])) {
- case PATHOPT:
- if (pathflag == LEAVEPATH)
- errorexit("Archiver options invalid", SHOWUSAGE);
- pathflag = LEAVEPATH;
- break;
- case MOVEOPT:
- if (moveflag == MOVEFILE)
- errorexit("Archiver options invalid", SHOWUSAGE);
- moveflag = MOVEFILE;
- break;
- default:
- errorexit("Archiver options invalid", SHOWUSAGE);
- }
- compos++;
- }
-
- /* Remove case dependancy of command */
- *command = tolower(*command);
-
- /* Check validity of supplied archiver command */
- if ((*command != LISTCOM) &&
- (*command != TESTCOM) &&
- (*command != EXTRACTCOM) &&
- (*command != DELETECOM) &&
- (*command != ADDCOM))
- errorexit("Invalid archiver command", SHOWUSAGE);
-
- /* Perform required action dependant upon user supplied command */
-
- switch(*command) {
-
- /* In the case of an archive listing request */
-
- case LISTCOM:
-
- /* Check archiver options are valid for this operation */
- if ((moveflag == MOVEFILE) || (pathflag == LEAVEPATH))
- errorexit("Archiver options invalid", SHOWUSAGE);
-
- /* Check number of arguments */
- if (argc != 3)
- errorexit("Wrong number of arguments", SHOWUSAGE);
-
- /* Open archive for input */
- if ((arc_fptr = fopen(argv[2], "r")) == NULL)
- errorexit("Can't open archive for input", SHOWUSAGE);
-
- /* Print header information */
- printf("Listing");
- pr_head(argv[2]);
-
- /* Perform listing operation */
- numfiles = listarc();
-
- /* Print tail information */
- pr_tail();
-
- /* Give operation statistics */
- operout("found",numfiles);
- succout("Listing", numerrors);
-
- /* Exit program cleanly */
- cleanexit(EXIT_SUCCESS);
-
-
- /* In the case of an archive deletion request */
-
- case DELETECOM:
-
- /* Check archiver options are valid for this operation */
- if ((moveflag == MOVEFILE) || (pathflag == LEAVEPATH))
- errorexit("Archiver options invalid", SHOWUSAGE);
-
- /* Check number of arguments */
- if (argc < 3)
- errorexit("Wrong number of arguments", SHOWUSAGE);
-
- /* Print header information */
- printf("Deleting from");
- pr_head(argv[2]);
-
- /* Perform deletion operation */
- numdel = deletearc(argv[2], argv, argc);
-
- /* Print tail information */
- pr_tail();
-
- /* Give operation statistics */
- operout("deleted", numdel);
- errsout(numerrors);
- succout("Deletion", numerrors);
-
- /* Exit program cleanly */
- if (numerrors == 0)
- cleanexit(EXIT_SUCCESS);
- else
- cleanexit(EXIT_FAILURE);
-
-
- /* In the case of an archive extraction/testing request */
-
- case TESTCOM:
- case EXTRACTCOM:
-
- /* Check archiver options are valid for this operation */
- if ((*command == TESTCOM) &&
- ((moveflag == MOVEFILE) || (pathflag == LEAVEPATH)))
- errorexit("Archiver options invalid", SHOWUSAGE);
-
- /* Check number of arguments */
- if ((*command == TESTCOM) && (argc != 3))
- errorexit("Wrong number of arguments", SHOWUSAGE);
- if ((*command != TESTCOM) && (argc < 3))
- errorexit("Not enough arguments", SHOWUSAGE);
-
- /* Open archive for input */
- if ((arc_fptr = fopen(argv[2], "r")) == NULL)
- errorexit("Can't open archive for input", SHOWUSAGE);
-
- /* Print header information */
- if (*command == TESTCOM)
- printf("Testing ");
- else
- printf("Extracting from ");
- pr_head(argv[2]);
-
- /* Perform extraction operation */
- numfiles = extractarc(*command, argv, argc);
-
- /* Print tail information */
- pr_tail();
-
- /* Give operation statistics */
- if (*command != TESTCOM) {
- operout("extracted", numfiles);
- errsout(numerrors);
- succout("Extraction", numerrors);
- }
- else {
- operout("tested", numfiles);
- errsout(numerrors);
- succout("Testing", numerrors);
- }
-
- /* In the case of a move option */
- if (moveflag == MOVEFILE) {
-
- /* If there were errors in extraction, don't */
- /* risk deleting from archive */
- if (numerrors != 0)
- printf("Not risking deleting from archive!\n");
-
- /* Otherwise, delete files that were extracted */
- else {
-
- /* Close the archive file first */
- COND_CLOSE(arc_fptr);
- arc_fptr = NULL;
-
- /* Print header information */
- printf("Deleting from");
- pr_head(argv[2]);
-
- /* Perform deletion operation */
- numdel = deletearc(argv[2], argv, argc);
-
- /* Print tail information */
- pr_tail();
-
- /* Give operation statistics */
- operout("deleted", numdel);
- errsout(numerrors);
- succout("Deletion", numerrors);
-
- }
-
- }
-
-
- /* Exit program cleanly */
- if (numerrors == 0)
- cleanexit(EXIT_SUCCESS);
- else
- cleanexit(EXIT_FAILURE);
-
-
- /* In the case of an add/move to an archive request */
-
- case ADDCOM:
-
- /* Check number of arguments */
- if (argc < 4)
- errorexit("Not enough arguments", SHOWUSAGE);
-
- /* Open archive for update */
- if ((arc_fptr = fopen(argv[2], "a")) == NULL)
- errorexit("Can't open archive", SHOWUSAGE);
-
- /* Print header information */
- if (*command == ADDCOM)
- printf("Adding to");
- else
- printf("Moving to");
- pr_head(argv[2]);
-
- /* Perform add operation */
- numfiles = addarc(argv, argc);
-
- /* Print tail information */
- pr_tail();
-
- /* Give operation statistics */
- if (*command == ADDCOM) {
- operout("added", numfiles);
- errsout(numerrors);
- succout("Adding", numerrors);
- }
- else {
- operout("moved", numfiles);
- errsout(numerrors);
- succout("Moving", numerrors);
- }
-
- /* Exit program cleanly */
- if (numerrors == 0)
- cleanexit(EXIT_SUCCESS);
- else
- cleanexit(EXIT_FAILURE);
-
- }
-
- /* By logic the program should never get this far */
- errorexit("Internal error - improper program execution", NOUSAGE);
- }
-